const PENDING = "pending"; //等待
const FULFILLED = "filfilled"; //成功
const REJECTED = "rejected"; //失败

class MyPromise {
  constructor(executor) {
    try {
      //executor 执行器，立即执行
      executor(this.resolve, this.reject);
    } catch (error) {
      this.reject(error);
    }
  }
  //promise状态
  status = PENDING;
  //成功后的值
  value = undefined;
  //失败的原因
  reason = undefined;
  //失败回调
  failCallback = [];
  //成功回调
  successCallback = [];
  //成功后的调用
  resolve = (value) => {
    //如果状态不是等待，阻止程序执行
    if (this.status !== PENDING) {
      return;
    }
    //将状态更改为成功
    this.status = FULFILLED;
    //保存成功后的值
    this.value = value;
    //判断成功回调是否存在 如果存在调用
    //this.successCallback && this.successCallback(this.value)
    while (this.successCallback.length) {
      this.successCallback.shift()();
    }
  };
  //失败后的调用
  reject = (reason) => {
    //如果状态不是等待，阻止程序执行
    if (this.status !== PENDING) {
      return;
    }
    //将状态更改为失败
    this.status = REJECTED;
    //保存失败的原因
    this.reason = reason;
    //判断成功回调是否存在 如果存在调用
    // this.failCallback &&this.failCallback(this.reason)
    while (this.failCallback.length) {
      this.failCallback.shift()();
    }
  };
  then(successCallback, failCallback) {
    //then方法参数可选，传递promise状态
    successCallback = successCallback ? successCallback : (value) => this.value;
    failCallback = failCallback
      ? failCallback
      : (reason) => {
          throw reason;
        };
    let promise2 = new MyPromise((resolve, reject) => {
      //判断状态
      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {
            //x：成功回调的返回值,then的链式调用时使用
            //判断x的值是普通值还是promise对象
            //如果是普通值直接调用resolve
            //如果是promise对象查看promise对象的返回结果
            //然后根据promise对象的返回结果，决定调用resolve，还是调用reject
            let x = successCallback(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      } else if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            //x：成功回调的返回值,then的链式调用时使用
            //判断x的值是普通值还是promise对象
            //如果是普通值直接调用resolve
            //如果是promise对象查看promise对象的返回结果
            //然后根据promise对象的返回结果，决定调用resolve，还是调用reject
            let x = failCallback(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      } else {
        //等待
        //将成功回调和失败后的回调存贮起来
        this.successCallback.push(() => {
          setTimeout(() => {
            try {
              //x：成功回调的返回值,then的链式调用时使用
              //判断x的值是普通值还是promise对象
              //如果是普通值直接调用resolve
              //如果是promise对象查看promise对象的返回结果
              //然后根据promise对象的返回结果，决定调用resolve，还是调用reject
              let x = successCallback(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
        this.failCallback.push(() => {
          setTimeout(() => {
            try {
              //x：成功回调的返回值,then的链式调用时使用
              //判断x的值是普通值还是promise对象
              //如果是普通值直接调用resolve
              //如果是promise对象查看promise对象的返回结果
              //然后根据promise对象的返回结果，决定调用resolve，还是调用reject
              let x = failCallback(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
      }
    });
    return promise2;
  }
  finally(callback){
    return this.then(value=>{
      return MyPromise.resolve(callback()).then(()=>value)
    },reason=>{
      return MyPromise.reject(callback()).then(()=>{throw reason})
    })
  }
  catch (failCallback){
    this.then(undefined,failCallback)
  }
  static all (array) {
    let result = [];
    let index = 0;
    return new MyPromise((resolve,reject)=>{
      function addData (key,value){
        result[key] = value;
        index++;//用于等待异步执行的结果
        if(index === array.length){
          resolve(result)
        }
      }
      for(let i =0;i<array.length;i++){
        let current = array[i];
        if(current instanceof MyPromise){
          //promise对象
          current.then(value=>addData(i,value),reason=>reject(reason))
        }else{
          //普通值
          addData(i,array[i])
        }
      }
    })
  }
  static resolve (value) {
    if(value instanceof MyPromise) return value;
    return new MyPromise(resolve=>resolve(value));
  }

}
function resolvePromise(promise2, x, resolve, reject) {
  //处理循环回调
  if (promise2 === x) {
    return reject(
      new TypeError("Chaning cycle detected for promise #<Promise>")
    );
  }
  if (x instanceof MyPromise) {
    //promise对象
    x.then(resolve, reject);
  } else {
    //普通值
    resolve(x);
  }
}
module.exports = MyPromise;
